using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Collections;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using SumGam.Globals;
using SumGam.Structs;
using SumGam.Classes;

namespace SumGam
{
    public class EntityManager
    {
        private List<BaseEntity> Entities;
        private List<int> FreeSlots;
        public EntityManager()
        {
            Entities = new List<BaseEntity>();
            FreeSlots = new List<int>();
        }
        private int GetFreeSlot()
        {
            int Slot = 0;
            if (FreeSlots.Count == 0)
            {
                Slot = Entities.Count;
            } 
            else
            {
                Slot = FreeSlots[0];
                FreeSlots.RemoveAt(0);
            }
            return Slot;
        }
        public bool AddEntity(BaseEntity Entity)
        {
            if (!Entities.Contains(Entity))
            {
                int Slot = GetFreeSlot();
                Entity.Slot = Slot;
                if (Slot == Entities.Count)
                {
                    Entities.Add(Entity);
                }
                else
                {
                    Entities[Slot] = Entity;
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        private void RemoveEntity(int Slot)
        {
            if (Slot != Entities.Count - 1) 
            {
            Entities[Slot] = new BaseEntity();
            Entities[Slot].Slot = Slot;
            FreeSlots.Add(Slot);
            }
        }
        public void Update()
        {
            //TODO: stress test this shit
            //System.Collections.ObjectModel.ReadOnlyCollection<BaseEntity> EntitiesCopy = Entities.AsReadOnly();
            for (int i = 0; i < Entities.Count; i++)
            {
                BaseEntity Entity = Entities[i];
                if (Entity.IsValid())
                {
                    if (!Entity.Initialized)
                    {
                        Entity.Initialize();
                        //Console.WriteLine("BITCHES");
                        Entity.Initialized = true;
                    }
                    Entity.Think();
                    if (Entity.Physical)
                    {
                        Entity.DoPhysics();
                    }
                }
            }
            for (int i = 0; i < Entities.Count; i++)
            {
                BaseEntity Entity1 = Entities[i];
                if (Entity1.IsValid() && Entity1.Initialized && Entity1.Physical)
                {
                    for (int j = i; j < Entities.Count; j++)
                    {
                        BaseEntity Entity2 = Entities[j];
                        if (Entity2.IsValid() && Entity2.Initialized && Entity2.Physical && Entity1 != Entity2)
                        {
                            if (Vector2.Distance(Entity1.Position, Entity2.Position) < Entity1.GetRadius() + Entity2.GetRadius())
                            {
                                if (Entity1.GetBoundingRectangle().Intersects(Entity2.GetBoundingRectangle()))
                                {
                                    Entity1.HandleCollision(Entity2);
                                    Entity2.HandleCollision(Entity1);
                                }
                                //Entity1.IsValid();
                            }
                            Entity1.IsValid();
                        }
                    }
                }
            }
            /*for (int i = 0; i < Entities.Count; i++)
            {
                BaseEntity Entity = Entities[i];
                if (Entity.IsValid() && Entity.ShouldRemove)
                {
                    RemoveEntity(Entity.Slot);
                }
            }*/
        }
        public void Draw()
        {
            for (int i = 0; i < Entities.Count; i++)
            {
                BaseEntity Entity = Entities[i];
                if (Entity.IsValid() && Entity.Initialized && Entity.Visible)
                {
                    Entity.Draw();
                }
            }
            //Entities.FindAll(p => p.Initialized && p.Visible && p.IsValid()).ForEach(p => p.Draw());
        }
        public List<BaseEntity> GetEntityList()
        {
            return Entities;
        }
    }
}